//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: Tracing.cs
//
//  Description: Traces different operations of the framework.
// 
//--------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Reflection;
using System.IO;
using Chili.Opf3.Query;
using System.Data;

namespace Chili.Opf3
{
	/// <summary>
	/// Class that traces the different operations of the framework.
	/// </summary>
	/// <remarks>
	/// This class traces the different operations of the framework. Please refer to the
	/// .NET documentation about how to create customized listener classes for this tracing
	/// utility. A listener class allows to specify the target of the trace output. Multiple
	/// listener classes can be registered with the <see cref="Tracing">Tracing</see> class.
	/// </remarks>
	public sealed class Tracing : TraceSource
	{
		private static Tracing _current;
#if TRACE
		private long _querycount;
#endif
 
		/// <summary>
		/// Static constructor.
		/// </summary>
		static Tracing()
		{
			// Create the instance of the tracing class.
			Assembly a = Assembly.GetAssembly(typeof(Tracing));
			_current = new Tracing(string.Format("Opf3 @ \"{0}\"", a.Location));
		}

		/// <summary>
		/// Creates an instance of the <see cref="Tracing">Tracing Class</see>.
		/// </summary>
		/// <param name="name">Specifies the name of the application.</param>
		private Tracing(string name)
			: base(name)
		{
			// Set the switch level to all. Just to get all output.
			this.Switch.Level = SourceLevels.All;
		}

		/// <summary>
		/// Returns the current instance of the <see cref="Tracing">Tracing</see> class.
		/// </summary>
		public static Tracing Current
		{
			get
			{
				return _current;
			}
		}

		/// <summary>
		/// Traces an error.
		/// </summary>
		/// <param name="message">The message of the error.</param>
		[Conditional("TRACE")]
		public void TraceError(string message)
		{
			base.TraceEvent(TraceEventType.Error, 0, message);
		}

		/// <summary>
		/// Traces an exception.
		/// </summary>
		/// <param name="ex">The exception that is traced.</param>
		[Conditional("TRACE")]
		public void TraceException(Exception ex)
		{
			base.TraceEvent(TraceEventType.Error, 1, "Caught exception: {0}", new object[] { ex });
		}

		/// <summary>
		/// Traces debug information.
		/// </summary>
		/// <param name="message">The debug information to trace.</param>
		[Conditional("TRACE")]
		public void TraceVerbose(string message)
		{
			base.TraceEvent(TraceEventType.Verbose, 3, message);
		}

		/// <summary>
		/// Traces a warning.
		/// </summary>
		/// <param name="message">The message of the warning.</param>
		[Conditional("TRACE")]
		public void TraceWarning(string message)
		{
			base.TraceEvent(TraceEventType.Warning, 4, message);
		}

		/// <summary>
		/// Traces a storage IO information.
		/// </summary>
		/// <param name="message">The message for the storage IO.</param>
		[Conditional("TRACE")]
		public void TraceStorageIO(string message)
		{
			base.TraceEvent(TraceEventType.Verbose, 5, message);
		}

		/// <summary>
		/// Traces an instance of the <see cref="CompiledQuery">CompiledQuery</see> class.
		/// </summary>
		/// <param name="query">The query to trace.</param>
		[Conditional("TRACE")]
		public void TraceStorageIO(CompiledQuery query)
		{
#if TRACE
			IDbCommand c = query.Command;

			// Check for an overflow.
			if (_querycount + 1 == long.MaxValue)
				_querycount = 0;

			StringBuilder sb = new StringBuilder();
			sb.AppendFormat("Executing query #{0} on the storage.\r\n", (++_querycount));
			sb.AppendLine(" - Query text: " + c.CommandText);
			sb.AppendLine(" - Parameters:");

			for (int i = 0; i < c.Parameters.Count; i++)
			{
				IDataParameter p = (IDataParameter)c.Parameters[i];

				sb.Append("   Parameter #" + (i + 1));
				sb.Append("; Name: " + p.ParameterName);
				sb.Append("; Value: " + p.Value);
				sb.AppendLine();
			}

			base.TraceEvent(TraceEventType.Verbose, 5, sb.ToString());
#endif
		}
	}
}
